﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using GA_Scheduler;


namespace GA_SCHEDULER_WPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : UserControl
    {
        System.Threading.Thread th;
        List<RoomControl> rooms = new List<RoomControl>();
        List<DayScheduleControl> dayList = new List<DayScheduleControl>();

        public MainWindow()
        {
            InitializeComponent();
            stopBut.IsEnabled = false;
            startBut.IsEnabled = false;

            //this. += new System.ComponentModel.CancelEventHandler(MainWindow_Closing);
            
        }

        void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (th != null)
            {
                th.Abort();
            }
        }

        void alg_NewBestSchedule(object sender, AlgorithmEventArgs e)
        {
            lock (this)
            {
                const int DAY_HOURS = 12;
                const int DAYS_NUM = 5;
                const int ROOM_CELL_WIDTH = 10;
                const int ROOM_CELL_HEIGHT = 10;
                const int ROOM_MARGIN_WIDTH = 10;
                const int ROOM_MARGIN_HEIGHT = 50;
                const int ROOM_COLUMN_NUMBER = DAYS_NUM + 1;
                const int ROOM_ROW_NUMBER = DAY_HOURS + 1;
                const int ROOM_TABLE_WIDTH = ROOM_CELL_WIDTH * ROOM_COLUMN_NUMBER + ROOM_MARGIN_WIDTH;
                const int ROOM_TABLE_HEIGHT = ROOM_CELL_HEIGHT * ROOM_ROW_NUMBER + ROOM_MARGIN_HEIGHT;

                int nr = Configuration.Instance.NumberOfRooms;

                var slots = e.BestSchedule.Slots;
                
                int i = 0;
               
                /*
                foreach (var sl in slots)
                {
                    if (sl.Count > 0)
                    {
                        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                        {
                            Border nBor = new Border();
                            int col = i % mainGrid.ColumnDefinitions.Count;
                            int row = i / mainGrid.ColumnDefinitions.Count;
                            if (col != 0) row++;

                            nBor.SetValue(Grid.RowProperty, row);
                            nBor.SetValue(Grid.ColumnProperty, col);
                           // nBor.SetValue(Grid.RowSpanProperty, sl[0].Duration);

                            nBor.Height = mainGrid.RowDefinitions[0].ActualHeight;
                            nBor.Width = mainGrid.ColumnDefinitions[0].ActualWidth;
                            nBor.BorderThickness = new Thickness(1);
                            nBor.BorderBrush = Brushes.Black;
                            mainGrid.Children.Add(nBor);
                        })
                       );
                    }
                    i++;
                }
                
                /*
                foreach (var cl in e.BestSchedule._classes.OrderBy( x=> x.Value ))
                {
                            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                            {
                                Border nBor = new Border() ;
                                int mNum = 0;
                                //for (int rNum = 0; rNum < 12; rNum++)

                                {
                                //    for (int cNum = 0; cNum < 49; cNum++)    
                                    {
                                        if(mNum == cl.Value)
                                        {
                                            nBor.SetValue(Grid.RowProperty, rNum);
                                            nBor.SetValue(Grid.ColumnProperty, cNum );
                                            break;
                                        }
                                        mNum++;
                                        
                                    }
                                    if(mNum == cl.Value)
                                        break;
                                }
                                nBor.SetValue(Grid.RowSpanProperty, cl.Key.Duration);
                                nBor.Height = mainGrid.RowDefinitions[0].ActualHeight * cl.Key.Duration;
                                nBor.Width = mainGrid.ColumnDefinitions[0].ActualWidth;
                                nBor.BorderThickness = new Thickness(1);
                                nBor.BorderBrush = Brushes.Black;
                                mainGrid.Children.Add(nBor);
                            }));
                }*/

                foreach (var d in dayList)
                {
                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                            {
                                label1.Content = "Population: " + e.Population;
                                label2.Content = "Fitness: " + e.BestSchedule.GetFitness();

                                d.Clear();
                            }));
                }

                foreach (var sl in slots)
                {
                    
                    int time = i % (nr * DAY_HOURS);
                    //int day = i / (nr * DAY_HOURS) + 1;
                    int day = i / (nr * DAY_HOURS);
                    int room = time / DAY_HOURS;
                    time = time % DAY_HOURS;
                    //time = time % DAY_HOURS + 1;

                    int l = room % 2;
                    int m = room / 2;
                    
                    if (sl.Count > 0)
                    {
                            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                            {
                                //rooms[room].AddNewCourse(day, time, 1, sl[0]._course.Name+"\n"+sl[0].Professor.Name+"\n\n"+"group");
                                foreach (var cc in sl)
                                {
                                    //foreach (var gr in sl[0].Groups)
                                    var groups = sl[0].GroupClasses;
                                    foreach (var gr in groups)
                                    {
                                       // dayList[day].AddNewCourse(time, gr.Groupd_ID, sl[0].Course.Name + "\n\n" + sl[0].Professor.Name + "\n" + Configuration.Instance.Rooms.First(r => r.Room_ID == room + 1 ).Name);
                                        //dayList[day].AddNewCourse(time, gr.Id, cc._course.Name + "\n\n" + cc.Professor.Name + "\n" + Configuration.Instance.GetRoomById(room).Name);
                                    }
                                }
                            }));

                    /*    var tt = sl[0];

                        //System.Threading.Thread.Sleep(1000);
                        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                            {
                                Border nBor = new Border();
                                nBor.Margin = new Thickness(
                                 ROOM_TABLE_WIDTH * l + ROOM_MARGIN_WIDTH + day * ROOM_CELL_WIDTH - 1,
                                 ROOM_TABLE_HEIGHT * m + ROOM_MARGIN_HEIGHT + time * ROOM_CELL_HEIGHT - 1, 0, 0
                                 );
                                nBor.Height = ROOM_CELL_HEIGHT;
                                nBor.Width = ROOM_CELL_WIDTH;
                                nBor.BorderThickness = new Thickness(1);
                                nBor.BorderBrush = Brushes.Black;
                                mainGrid.Children.Add(nBor);
                            })
                       );
                     * */
                    }
                    i++;

                }

            }
        }

        private void openBut_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.stackPanel1.Children.Clear();

                /* Configuration conf = new Configuration();

                 Microsoft.Win32.OpenFileDialog fileDialog = new Microsoft.Win32.OpenFileDialog();
                 bool? b = fileDialog.ShowDialog(this);
                 string fileName;

                 if (b == true)
                 {
                     fileName = fileDialog.FileName;
                 }
                 else
                 {
                     return;
                 }

                 if (!System.IO.File.Exists(fileName))
                 {
                     MessageBox.Show(fileName + " NOT FOUND", "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
                     return;
                 }

                 Configuration.Instance.ParseFile(fileName);
                 */
                for (int i = 1; i < 8; i++)
                {
                    DayScheduleControl dcntrl = new DayScheduleControl()
                    {
                        DayOfTheWeek = i,
                        Groups = Configuration.Instance.Groups.ToList(),
                        Margin = new Thickness(10, 40, 0, 0),
                        Height = 900
                    };
                    dayList.Add(dcntrl);
                    stackPanel1.Children.Add(dcntrl);
                }

                stopBut.IsEnabled = false;
                openBut.IsEnabled = false;
                startBut.IsEnabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        AlgorithmDB algdb;

        private void startBut_Click(object sender, RoutedEventArgs e)
        {
            startBut.IsEnabled = false;

            algdb = new AlgorithmDB();
            algdb.NewBestSchedule += new EventHandler<AlgorithmDBEventArgs>(algdb_NewBestSchedule);
            algdb.StateChanged += new EventHandler<AlgorithmDBStateEventArgs>(algdb_StateChanged);
            th = new System.Threading.Thread(algdb.Start);
            th.Start();
            stopBut.IsEnabled = true;
        }

        void algdb_StateChanged(object sender, AlgorithmDBStateEventArgs e)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
            {
                switch (e.State)
                {
                    case AlgorithmState.AS_CRITERIA_STOPPED:
                        startBut.IsEnabled = true;
                        openBut.IsEnabled = true;
                        stopBut.IsEnabled = false;
                        break;
                    case AlgorithmState.AS_USER_STOPED:
                        startBut.IsEnabled = true;
                        openBut.IsEnabled = true;
                        stopBut.IsEnabled = false;
                        break;
                }
            }));
        }

        void algdb_NewBestSchedule(object sender, AlgorithmDBEventArgs e)
        {
            lock (this)
            {
                int nr = Configuration.Instance.NumberOfRooms;

                var slots = e.BestSchedule;

                int i = 0;

                foreach (var d in dayList)
                {
                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        label1.Content = "Population: " + e.Population;
                        label2.Content = "Fitness: " + e.BestSchedule.Fitness;

                        d.Clear();
                    }));
                }
                
                foreach (var sl in slots.Genes)
                {


                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        dayList[sl.DayOfWeek].AddNewCourse(sl);
                        //var groups = sl.Class.GroupClasses;
                        //foreach (var gr in groups)
                        //{
                        //    dayList[sl.DayOfWeek].AddNewCourse(sl.Pair, gr.Groupd_ID, sl.Class.Course.Name + "\n\n" + sl.Class.Professor.Name + "\n" + sl.Room.Name);
                        //}
                            
                    }));

                    
                    i++;
                
                }
                
            }
        }

        void alg_StateChanged(object sender, AlgorithmStateEventArgs e)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
            {
                switch (e.State)
                {
                    case AlgorithmState.AS_CRITERIA_STOPPED:
                        startBut.IsEnabled = true;
                        openBut.IsEnabled = true;
                        stopBut.IsEnabled = false;
                        break;
                    case AlgorithmState.AS_USER_STOPED:
                        startBut.IsEnabled = true;
                        openBut.IsEnabled = true;
                        stopBut.IsEnabled = false;
                        break;
                }
            }));
        }

        private void stopBut_Click(object sender, RoutedEventArgs e)
        {
            algdb.Stop();
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            
        }

        private void stopBut_Click_1(object sender, RoutedEventArgs e)
        {
            algdb.Stop();
        }

    }
}
